package de.pixel83.piecemaster.ai;

import java.util.ArrayList;
import java.util.ArrayList;

import de.pixel83.piecemaster.Board;
import de.pixel83.piecemaster.Move;
import de.pixel83.piecemaster.Square;

public class NotMasterAi implements Ai {
	private int p = 100;
	private int n = 300;
	private int b = 350; // eindeutig erhöhen
	private int r = 500;
	private int q = 1000;
	private int k = 10000;

	private Move m0;

	public String getName() {
		return "NotMasterAi";
	}

	public Move draw(Board board, char color) {
		MoveRatingCombo mrc = null;

		ArrayList<Move> legalMoves = new ArrayList<Move>();
		ArrayList<Square> ownPieces = getAllPieces(board, color);
		for (Square square : ownPieces) {
			legalMoves.addAll(board.getLegalMoves(square));
		}

		int finalRating = negaMax(board, 3, true, color);
		System.out.println("#################### Final rating: " + finalRating);

		/*
		 * int bestWorstCaseRating = -10000; Move bestMove = null; for (Move mov
		 * : legalMoves) { Board tempBoard = new Board(board.toString());
		 * tempBoard.move(mov); mrc = getBestMove(tempBoard,
		 * Board.invertColor(color)); if (mrc.getRating() * -1 >
		 * bestWorstCaseRating) { bestMove = mov; bestWorstCaseRating =
		 * mrc.getRating() * -1; } }
		 * System.out.println("#################### Best move would be " +
		 * bestMove.toString() + " resulting in worst case " +
		 * bestWorstCaseRating);
		 */

		return m0;
	}

	private int negaMax(Board board, int depth, boolean top, char color) {
		// TODO: Catch WIN and DRAW
		if (depth <= 0) {
			return rateBoard(board, color);
		}

		ArrayList<Move> legalMoves = new ArrayList<Move>();
		ArrayList<Square> ownPieces = getAllPieces(board, board.getColor());
		for (Square square : ownPieces) {
			legalMoves.addAll(board.getLegalMoves(square));
		}

		Board tempBoard = new Board(board.toString());
		tempBoard.move(legalMoves.get(0));
		int bestValue = -negaMax(tempBoard, depth - 1, false, color);
		tempBoard = null;

		if (top && legalMoves.size() >= 0)
			this.m0 = legalMoves.get(0);

		for (Move mov : legalMoves) {
			tempBoard = new Board(board.toString());
			tempBoard.move(mov);
			int value = -negaMax(tempBoard, depth - 1, false, color);
			if (value > bestValue) {
				bestValue = value;
				if (top)
					this.m0 = mov;
			}
		}
		// logRating(bestValue, depth);
		return bestValue;
	}

	private void logRating(int value, int depth) {
		String text = "#################### ";
		for (int i = 0; i < depth; i++) {
			text += "#";
		}
		text += " Rating: " + value;
		System.out.println(text);
	}

	private MoveRatingCombo getBestMove(Board board, char color) {
		ArrayList<Move> legalMoves = new ArrayList<Move>();
		ArrayList<Square> ownPieces = getAllPieces(board, color);
		for (Square square : ownPieces) {
			legalMoves.addAll(board.getLegalMoves(square));
		}

		int bestRating = -10000;
		Move bestMove = null;
		for (Move mov : legalMoves) {
			Board tempBoard = new Board(board.toString());
			tempBoard.move(mov);
			int rating = rateBoard(tempBoard, color);
			if (bestMove == null || rating > bestRating) {
				bestRating = rating;
				bestMove = mov;
			}
		}

		return new MoveRatingCombo(bestMove, bestRating);
	}

	private ArrayList<Square> getAllPieces(Board board, char color) {
		ArrayList<Square> list = new ArrayList<Square>();
		for (int r = 0; r < 6; r++) {
			for (int c = 0; c < 5; c++) {
				if (board.getColor(board.getPieceAt(r, c)) == color) {
					list.add(new Square(c, r));
				}
			}
		}
		return list;
	}

	private int rateBoard(Board board) {
		return rateBoard(board, 'W');
	}

	private int rateBoard(Board board, char color) {
		int rating = 0;
		for (int r = 0; r < 6; r++) {
			for (int c = 0; c < 5; c++) {
				rating += getValue(board, r, c, color);
			}
		}
		return rating;
	}

	private int getValue(Board board, int row, int col, char color) {
		int value = 0;
		char piece = board.getPieceAt(row, col);
		int factor = (Board.getColor(piece) == color ? 1 : -1);
		piece = Character.toLowerCase(piece);
		switch (piece) {
		case 'p':
			value = p;
			// Pawns closer to promotion are more valuable
			if (color == 'W')
				value += (50 * row);
			if (color == 'B')
				value += (50 * (5 - row));
			break;
		case 'n':
			value = n;
			break;
		case 'b':
			value = b;
			break;
		case 'r':
			value = r;
			break;
		case 'q':
			value = q;
			break;
		case 'k':
			value = k;
			break;
		}
		value = value * factor;
		return value;
	}

	/**
	 * Tests the class RandomAi
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		Board board = new Board();
		Ai ai = new NotSoRandomAi();
		for (int i = 0; i < 3; i++)
			System.out.println(ai.draw(board, 'W'));
	}

}
